package org.dding.msc.service;

import java.util.Collection;

import org.dding.msc.exception.ServiceRegistryException;
import org.dding.msc.value.Value;

/**
 * A builder for an individual service in a {@code ServiceTarget}.  Create an instance via the
 * {@link ServiceTarget#addService(ServiceName, Service)}, 
 * {@link ServiceTarget#addServiceValue(ServiceName, Value)} or
 * methods.
 *
 * @param <T> the service type
 *
 */
public interface ServiceBuilder<T> {

    /**
     * Add aliases for this service.
     *
     * @param aliases the service names to use as aliases
     * @return the builder
     */
    ServiceBuilder<T> addAliases(ServiceName... aliases);

    /**
     * Set the initial mode.
     *
     * @param mode the initial mode
     * @return this builder
     */
    ServiceBuilder<T> setInitialMode(ServiceController.Mode mode);

    /**
     * Add a service listener that will be added to this service.
     *
     * @param listener the listener to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(ServiceListener<? super T> listener);

    /**
     * Add service listeners that will be added to this service.
     *
     * @param listeners a list of listeners to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(ServiceListener<? super T>... listeners);

    /**
     * Add service listeners that will be added to this service.
     *
     * @param listeners a collection of listeners to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(Collection<? extends ServiceListener<? super T>> listeners);

    /**
     * Add a service listener that will be added to this service.
     *
     * @param inheritance the inheritance type for this listener
     * @param listener the listener to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(ServiceListener.Inheritance inheritance, ServiceListener<? super T> listener);

    /**
     * Add service listeners that will be added to this service.
     *
     * @param inheritance the inheritance type for this listener
     * @param listeners a list of listeners to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(ServiceListener.Inheritance inheritance, ServiceListener<? super T>... listeners);

    /**
     * Add service listeners that will be added to this service.
     *
     * @param inheritance the inheritance type for this listener
     * @param listeners a collection of listeners to add to the service
     * @return this builder
     */
    ServiceBuilder<T> addListener(ServiceListener.Inheritance inheritance, Collection<? extends ServiceListener<? super T>> listeners);

    /**
     * Install the defined service into the container.
     *
     * @return the installed service controller
     * @throws ServiceRegistryException if installation fails
     * @throws IllegalStateException    if installation has been performed previously
     */
    ServiceController<T> install() throws ServiceRegistryException, IllegalStateException;
}
